/*
 * @Author: yangrongxin
 * @Date: 2021-08-05 14:19:31
 * @LastEditors: guoju
 * @LastEditTime: 2022-01-13 16:57:39
 */
import { useCallback, useEffect, useMemo, useState, useReducer } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { View, Text, ScrollView, Button, Image } from '@tarojs/components';
import { CHANNEL_TYPE } from '@/pages/My/compoents/MyAssessment/dataDictionary';
import type { QuestionsInfo, SelectData } from '@/types/exam.d';
import { QUESTION_TYPE, SPEED_TYPE, EXTEND_TYPE, INPUT_TYPE } from '@/types/exam.d';
import type { SelectDataValue } from './components/index.d';
import { SingleSelect, MuiltSelect, NpsSelect, FillSelect, MatrixSelect } from './components';
import styles from './index.module.less';

let timer: any = null;
let seconds: number = 0; // 用于获取当前的答题时间

interface ExamContentProps {
  questions: QuestionsInfo
  curQuestionIndex: number
  submitQuestionInfoList: SelectData[]
  submitQuestion: (answer: SelectData) => void
  backToPrevAnswer: (answer: SelectData) => void
  evaluationType: string;
  isLast: boolean;
  loading: boolean;
}

type UpdateData = {
  [k in keyof SelectData]
}

function reducer(state, action): UpdateData {
  if ( action.type === 'update' ) {
    return {
      ...state,
      ...action.payload
    };
  }
  return state;
}

const ExamContent = (props: ExamContentProps) => {
  const {
    questions: {
      questionId,
      extend,
      title,
      type,
      image,
      subtitles,
      isMutual,
      minNum,
      maxNum,
    },
    curQuestionIndex,
    submitQuestionInfoList = [],// 所有问题的答案集合
    submitQuestion,
    backToPrevAnswer,
    isLast,
    loading,
    evaluationType
  } = props;

  const dispatchs = useDispatch();
  const {
    examData: { questions = [] },
    jumpQuestions = [],
  } = useSelector((state: any) => state.evaluation);

  const [selectContent, dispatch] = useReducer(reducer, {
    questionId,
    type,
    answer: [],
    label: [],
    payload: [],
    text: '',
  });

  // 当前选中题目的答案集合
  const curAnswer = submitQuestionInfoList[curQuestionIndex];

  // 用户现在选项的时候的修改记录 TODO: 需要知道ts 如何获取对应的typs定义对象中的指定属性名称的类型
  const [modifyRecords, setModifyRecords] = useState<any[]>(curAnswer?.modifyRecords || []);

  // 更新当前的state数据
  const setSelectContent = (payload: SelectDataValue) => {
    dispatch({
      type: 'update',
      payload
    });
  };

  useEffect(() => {
    // 更换当前题目的时候刷新当前的参数
    if (curAnswer) {
      setSelectContent({
        questionId,
        type,
        answer: curAnswer.answer,
        label: curAnswer.label,
        payload: curAnswer.payload,
        text: curAnswer.text,
      });
      setModifyRecords(curAnswer.modifyRecords || []);
    } else {
      setSelectContent({
        questionId,
        type,
        answer: [],
        label: [],
        payload: [],
        text: '',
      });
      setModifyRecords([]);
    }
    beginTimer();
  }, [questionId]);

  // 清空计时并开始新的计时
  const beginTimer = () => {
    clearInterval(timer);
    seconds = 0;
    timer = setInterval(() => {
      seconds += 1;
    }, 1000);
  };

  useEffect(() => {
    beginTimer();
    return () => {
      clearInterval(timer);
    };
  }, []);

  const getQuestionType = useCallback((questionType: QUESTION_TYPE) => {
    switch(questionType) {
      case QUESTION_TYPE.SINGLE: return '单选';
      case QUESTION_TYPE.MUILT: return '多选';
      case QUESTION_TYPE.NPS: return 'NPS';
      case QUESTION_TYPE.FILL: return '填空';
      case QUESTION_TYPE.MATRIX: return '矩阵';
      default: return '未知题型' ;
    }
  }, [type]);

  const RenderTopic = useMemo(() => {
    switch (type) {
      case QUESTION_TYPE.SINGLE: return SingleSelect;
      case QUESTION_TYPE.MUILT: return MuiltSelect;
      case QUESTION_TYPE.NPS: return NpsSelect;
      case QUESTION_TYPE.FILL: return FillSelect;
      case QUESTION_TYPE.MATRIX: return MatrixSelect;
      default: return SingleSelect;
    }
  }, [type]);

  // 判断是否能下一步
  const isCanNext = () => {
    // 填空题
    if (type === QUESTION_TYPE.FILL) {
      const { min, max, inputType } = extend;
      if (inputType === INPUT_TYPE.TEXT) {
        return (
          selectContent.text.length >= min && selectContent.text.length <= max
        );
      } else {
        return selectContent.text >= min && selectContent.text <= max;
      }
    }
    // 矩阵题
    if (type === QUESTION_TYPE.MATRIX) {
      const isChecked =
        selectContent.answer.length === 0 ||
        selectContent.answer.includes(null as never);
      return !isChecked;
    }
    // 单选题子选项
    if (
      type === QUESTION_TYPE.SINGLE &&
      selectContent.optionType === EXTEND_TYPE.CHILD
    ) {
      return selectContent.payload.length !== 0;
    }
    return selectContent.answer.length !== 0;
  };

  // 设置选中的答案及选项历史记录
  const setCheckAnswer = (
    newAnswerObj: SelectData,
    jumpQuestionId: any = '',
  ) => {
    // 更新当前选中的数据
    setSelectContent(newAnswerObj);

    // 填空题/矩阵不记录
    if (type === QUESTION_TYPE.FILL || type === QUESTION_TYPE.MATRIX) return;

    if (type === QUESTION_TYPE.SINGLE) {
      // 单选题 输入框和子选项时不重复记录
      if (!newAnswerObj.label) return;

      const { optionType = -1 } = newAnswerObj;
      let jumpList: any = JSON.parse(JSON.stringify(jumpQuestions));

      // 单选题 选择跳题的选项后 记录当前序列号及跳题的序列号
      if (optionType === EXTEND_TYPE.JUMP) {
        // 通过id获取跳题的信息
        questions.forEach((item: any, index: number) => {
          if (item.questionId === jumpQuestionId) {
            const jump = {
              questionId, // 当前跳题选项的单选题id
              curIndex: curQuestionIndex, // 当前跳题选项的单选题序号
              jumpIndex: index, // 要跳题的序号
            };
            const i = jumpList.findIndex((item: any) => item.questionId === questionId);
            if(i > -1){
              jumpList[i] = jump;
            }else{
              jumpList.push(jump);
            }
          }
        });
        dispatchs({
          type: 'evaluation/updateExamData',
          payload: {
            jumpQuestions: jumpList,
          },
        });
      }
      // 选择非跳题的选项后 清空已记录的序列号及跳题的序列号
      else if (jumpList.length > 0) {
        // 通过当前问题id获取是否存在跳题列表中以及index,
        const index = jumpList.findIndex(
          (item: any) => item.questionId === questionId,
        );

        // 如果当前跳题存在, 重置当前题的跳题逻辑
        if (index > -1) {
          jumpList.splice(index, 1);
          dispatchs({
            type: 'evaluation/updateExamData',
            payload: {
              jumpQuestions: jumpList,
            },
          });
        }
      }
    }

    let recordsList: any = {};
    if (type === QUESTION_TYPE.NPS) {
      recordsList = newAnswerObj.answer[0];
    }
    if (newAnswerObj.label) {
      recordsList = {
        label: newAnswerObj.label,
        answerId: newAnswerObj.answer,
      };
    }
    const modifyList = [...modifyRecords, recordsList];

    // 仅存储最近十次的选中数据
    setModifyRecords(modifyList.splice(-10));
  };

  return (
    <View className={styles.topicContainer}>
      {/* 题目类型 */}
      <View className={styles.topicType}>
        <Text>{getQuestionType(type)}</Text>
      </View>
      {/* 标题 */}
      <View className={styles.topicTitle}>
        <Text>{title}</Text>
        {image && (
          <View className={styles.image}>
            <Image src={image} />
          </View>
        )}
      </View>
      {/* 问题列表 */}
      <ScrollView scrollY scrollWithAnimation className={styles.topicContent}>
        <RenderTopic
          extend={extend}
          subtitles={subtitles}
          answer={selectContent.answer}
          label={selectContent.label}
          payload={selectContent.payload}
          text={selectContent.text}
          isMutual={isMutual}
          setAnswer={(newAnswerObj: SelectData, jumpQuestionId: any) =>
            setCheckAnswer(newAnswerObj, jumpQuestionId)
          }
        />
      </ScrollView>
      {/* 展示上一题与下一题的按钮 并且点击能够进行跳转 */}
      <View className={styles.footer}>
        <Button
          className={`${styles.submitBtn} ${curQuestionIndex === 0 ? styles.submitBtnDisabled : ''}`}
          onClick={() => {
            if (curQuestionIndex !== 0) { // 当前不是第一题 可以返回上一题
              // 院内测评 进行上一题的时候 需要更新历史选择 以及使用时间等参数
              if (Number(evaluationType) === CHANNEL_TYPE.THECOURT) {
                backToPrevAnswer({
                  ...selectContent,
                  modifyRecords,
                  useTime: curAnswer?.useTime || seconds,
                  speedType: curAnswer?.speedType || (seconds < minNum ? SPEED_TYPE.SLOWER : seconds > maxNum ? SPEED_TYPE.FASTER : SPEED_TYPE.NORMAL),
                });
              } else {
                backToPrevAnswer(selectContent);
              }
            }
          }}
        >
          上一题
        </Button>
        <Button
          className={`${styles.submitBtn} ${!isCanNext() ? styles.submitBtnDisabled : ''}`}
          onClick={() => {
            if (isCanNext()) {
              if (Number(evaluationType) === CHANNEL_TYPE.THECOURT) {
                submitQuestion({
                  ...selectContent,
                  modifyRecords,
                  useTime: curAnswer?.useTime || seconds,
                  speedType: curAnswer?.speedType || (seconds < minNum ? SPEED_TYPE.SLOWER : seconds > maxNum ? SPEED_TYPE.FASTER : SPEED_TYPE.NORMAL),
                });
              } else {
                submitQuestion(selectContent);
              }
            }
          }}
          loading={loading}
        >
          {isLast ? '完成测试' : '下一题'}
        </Button>
      </View>
    </View>
  );
};

export default ExamContent;
